;(function($){

	var defaults = {
		closest: 'a'
	};

	function onlyScroller(elements, options)
	{
		this.elements = elements;
		this.config = $.extend({}, defaults, options);

		if(this.elements.length){
			var self = this;

			self.init();
			$(window).on('load resize', function(e){
				self.init();
			});

			$(window).on('scroll', function(e){
				self.onScroll(e);
			});

			self.elements.on('click', function(e){
				onClick(e);
			});
		}
	}

	function onClick(e)
	{
		var element = e.target;
		var target = sanitizeSelector($(element).data('target') ? $(element).data('target') : element.hash);
		if ($(target).length > 0)
		{
			e.preventDefault();
			scrollTop($(target).offset().top, function () {
				window.location.hash = target;
			});
		}
	};

	function scrollTop(top, complete)
	{
		var callback = $.isFunction(complete) ? complete : {};
		var properties = {'scrollTop': top};
		$('html, body').stop().animate(properties, 900, 'swing', callback);
	}

	function scroll(target, options, properties)
	{
		var target = sanitizeSelector(target);
		if ($(target).length > 0)
		{
			var defaultProperties = {'scrollTop': top},
				defaultOptions = {
					duration: 900,
					easing: 'swing',
					complete: function () {
						window.location.hash = target;
					}
				};

			options = $.extend({}, defaultOptions, options);
			properties = $.isPlainObject(properties) ? properties : {'scrollTop': top};

			$.extend({}, defaultProperties, properties);

			var properties = $.isPlainObject(top) ? properties : {'scrollTop': top};
			var callback = $.isFunction(callback) ? callback : function(){};
			$('html, body').stop().animate(properties, 900, 'swing', callback);

		}
	};

	function sanitizeSelector(target){
		var target = $.trim(target);
		return !!target ? ('#'+target.substr(1).replace(/([ #.!"$%&'()*+,\/:;<=>?@[\\\]^`{|}~])/g,'\\$1')) : target;
	};

	onlyScroller.prototype.init = function()
	{
		this.offsets = [];
		this.closests = $([]); // Обертки или сами элементы
		var elements = $([]);
		if(this.elements.length){
			var self = this;
			this.elements.each(function(index)
			{
				var $target = $(sanitizeSelector(this.hash));
				if ($target.length > 0){
					var closest = self.closestOrElement(this);
					self.closests = self.closests.add(closest);
					self.offsets.push({offset: $target.offset(), element: $(this), closest: closest});
					elements = elements.add(this);
				}
			});
		}
		this.elements = elements;
	};

	onlyScroller.prototype.onScroll = function(e)
	{
		if(this.offsets.length){
			var active = {};
			var scrollTop = $(window).scrollTop();
			var self = this;
			$.each(self.offsets, function()
			{
				if (scrollTop < Math.floor(self.offsets[0].offset.top)){
					active = self.offsets[0];
				} else if (scrollTop >= Math.floor(this.offset.top)){
					active = this;
				}
				if($(window).scrollTop() + $(window).height() == $(document).height()) {
					active = self.offsets[self.offsets.length-1];
				}

			});
			if (!$.isEmptyObject(active) && !active.closest.hasClass('active')){
				this.closests.removeClass('active');
				active.closest.addClass('active');
			}
		}
	};

	onlyScroller.prototype.closestOrElement = function(elements)
	{
		var context = $([]);
		var self = this;
		$.each($(elements), function()
		{
			var closest = $(this).closest(self.config.closest);
				closest = closest.length ? closest : this;
			context = context.add(closest);
		});
		return context;
	};

	$.onlyScroller = $.fn.onlyScroller = function(options)
	{
		var scroller = new onlyScroller(this, options);
		return this;
	};

	$.fn.onlyScroller.scrollTop = scrollTop;

	$('body').on('click', '[data-toggle="only.scroller"]', function (e) {
		onClick(e);
	});

})(jQuery);